package com.robot.common.enums;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedJdbcTypes({JdbcType.VARCHAR, JdbcType.INTEGER})
@MappedTypes(Enum.class)
public class EnumTypeHandler<E extends Enum<E> & ValueProvider<?>>extends BaseTypeHandler<E> {

    private final Class<E> enumClass;

    public EnumTypeHandler(Class<E> enumClass) {
        this.enumClass = enumClass;
    }
    // 添加一个静态工厂方法
    public static <T extends Enum<T> & ValueProvider<?>> EnumTypeHandler<T> create(Class<T> enumClass) {
        return new EnumTypeHandler<>(enumClass);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        if (jdbcType == JdbcType.VARCHAR) {
            ps.setString(i, parameter.getValue().toString());
        } else if (jdbcType == JdbcType.INTEGER) {
            ps.setInt(i, (Integer) parameter.getValue());
        }
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Object value = getValueFromResultSet(rs, columnIndex);
        return convertToEnum(value);
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 先通过列名获取列索引
        int columnIndex = 0;
        try {
            columnIndex = rs.findColumn(columnName);
        } catch (SQLException e) {
            throw new RuntimeException("无法找到列名：" + columnName, e);
        }
        return getNullableResult(rs, columnIndex);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Object value = getValueFromCallableStatement(cs, columnIndex);
        return convertToEnum(value);
    }

    private Object getValueFromResultSet(ResultSet rs, int columnIndex) throws SQLException {
        int columnType = rs.getMetaData().getColumnType(columnIndex);
        if (columnType == java.sql.Types.INTEGER) {
            return rs.getInt(columnIndex);
        } else {
            return rs.getString(columnIndex);
        }
    }

    private Object getValueFromCallableStatement(CallableStatement cs, int columnIndex) throws SQLException {
        int columnType = cs.getMetaData().getColumnType(columnIndex);
        if (columnType == java.sql.Types.INTEGER) {
            return cs.getInt(columnIndex);
        } else {
            return cs.getString(columnIndex);
        }
    }

    private E convertToEnum(Object value) {
        if (value == null) {
            return null;
        }
        for (E enumValue : enumClass.getEnumConstants()) {
            if (enumValue.getValue().equals(value)) {
                return enumValue;
            }
        }
        return null;
    }
}